package br.com.toscano.contpedido.business;

import java.io.BufferedReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;

import javax.inject.Inject;

import br.com.toscano.contpedido.domain.Cliente;
import br.com.toscano.contpedido.domain.Pedido;
import br.com.toscano.contpedido.domain.Recebimento;
import br.com.toscano.contpedido.domain.StatusPedido;
import br.com.toscano.contpedido.exception.DescricaoException;
import br.com.toscano.contpedido.otd.ClienteOTD;
import br.com.toscano.contpedido.persistence.ClienteDAO;
import br.com.toscano.contpedido.persistence.PedidoDAO;
import br.com.toscano.contpedido.persistence.RecebimentoDAO;
import br.com.toscano.contpedido.util.Util;
import br.gov.frameworkdemoiselle.stereotype.BusinessController;
import br.gov.frameworkdemoiselle.template.DelegateCrud;
import br.gov.frameworkdemoiselle.transaction.Transactional;

@BusinessController
public class ClienteBC extends DelegateCrud<Cliente, Long, ClienteDAO> {
	
	private static final long serialVersionUID = 1L;
	
	@Inject
	private PedidoDAO pedidoDAO;

	@Inject
	private RecebimentoDAO recebimentoDAO;

	@Override
	@Transactional
	public void delete(Long id) {
		this.getDelegate().delete(id);
	}

	@Override
	@Transactional
	public void delete(List<Long> ids) {
		// TODO Auto-generated method stub
		for (Long id : ids) {
			this.delete(id);
		}
	}

	public List<Cliente> pesquisarCliente(String telefone, String nome) {
		return this.getDelegate().pesquisarCliente(telefone, nome);
	}

	public List<ClienteOTD> gerarExtratoPorPeriodo(Date dataInicial, Date dataFinal) {
		List<ClienteOTD> retorno = new ArrayList<ClienteOTD>();
		
		if (dataInicial != null) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(dataInicial);
			cal.set(Calendar.HOUR_OF_DAY,0);
			cal.set(Calendar.MINUTE,0);
			cal.set(Calendar.SECOND,0);
			dataInicial = cal.getTime();
		}
		
		if (dataFinal != null) {
			Calendar cal = Calendar.getInstance();
			cal.setTime(dataFinal);
			cal.set(Calendar.HOUR_OF_DAY,23);
			cal.set(Calendar.MINUTE,59);
			cal.set(Calendar.SECOND,59);
			dataFinal = cal.getTime();
		}
		
		List<Pedido> lista = pedidoDAO.consultarPedidos(null, null, null, null, null, null,null, null, null, null, null, null);
		for(Pedido pedido : lista) {
			if (!pedido.getStatusPedido().getId().equals(StatusPedido.CANCELADO)) {
				ClienteOTD novo = null;
				for(ClienteOTD cadastrado : retorno) {
					if (cadastrado.getIdCliente().equals(pedido.getCliente().getId())) {
						novo = cadastrado;
						break;
					}
				}

				if (novo == null) {
					novo = new ClienteOTD();
					retorno.add(novo);
				}

				novo.setIdCliente(pedido.getCliente().getId());
				novo.setNomeCliente(pedido.getCliente().getNome());
				if (dataInicial != null && dataInicial.getTime() > pedido.getDataEntrega().getTime()) {
				// pedido antes 
					novo.setValorPedidoAnterior(novo.getValorPedidoAnterior().add(pedido.getValorTotalPedido()));
				} else if (dataFinal != null && dataFinal.getTime() < pedido.getDataEntrega().getTime()) {
				// pedido depois

				} else {
					novo.setValorPedido(novo.getValorPedido().add(pedido.getValorTotalPedido()));
				}
			}
		}
		
		List<Recebimento> listaRecebimento = recebimentoDAO.consultarRecebimento(null, null, null, null, null);
		for(Recebimento recebimento : listaRecebimento) {
			ClienteOTD novo = null;
			for(ClienteOTD cadastrado : retorno) {
				if (cadastrado.getIdCliente().equals(recebimento.getCliente().getId())) {
					novo = cadastrado;
					break;
				}
			}
			
			if (novo == null) {
				novo = new ClienteOTD();
				retorno.add(novo);
			}
			
			novo.setIdCliente(recebimento.getCliente().getId());
			novo.setNomeCliente(recebimento.getCliente().getNome());
			if (dataInicial != null && dataInicial.getTime() > recebimento.getDataRecebimento().getTime()) {
			// Recebimento antes 
				novo.setValorPagamentoAnterior(novo.getValorPagamentoAnterior().add(recebimento.getValorTotalRecebimento()));
			} else if (dataFinal != null && dataFinal.getTime() < recebimento.getDataRecebimento().getTime()) {
			// Recebimento depois

			} else {
				novo.setValorPagamento(novo.getValorPagamento().add(recebimento.getValorTotalRecebimento()));
			}
		}

		Collections.sort(retorno, new Comparator<ClienteOTD>() {
			  public int compare(ClienteOTD p1, ClienteOTD p2) {

			      return p1.getNomeCliente().compareTo(p2.getNomeCliente());
			  }
			});
		
		return retorno;
	}

	@Transactional
	public List<Cliente> importarPlanilha(String separado,BufferedReader in) throws IOException {
		List<Cliente> listaCliente = new ArrayList<Cliente>();
		
		int quantidadeCampo = 14;
		String linha = null;
		int cont = 1;
		while((linha = in.readLine()) != null) {
			String line = linha;
			if (!line.toLowerCase().startsWith("nome") && !line.toLowerCase().startsWith("nome") ) {
				if (Util.contarSubString(line, separado) < quantidadeCampo) {
					line = line + separado; 
					while (Util.contarSubString(line, separado) < quantidadeCampo) {
						line = line + separado; 
					}
				}
				if (Util.contarSubString(line, separado) != quantidadeCampo) {
					throw new DescricaoException("A linha " + cont + " deveria ter apenas " + quantidadeCampo + " campos !");
				}
				while(line.indexOf(separado
						+ separado ) != -1) {
					line = line.replace(separado + separado ,separado + " " + separado );
				}
			    StringTokenizer st = new StringTokenizer(line, separado);
			    try {
				    String nome = st.nextToken().trim();
				    String responsavel = st.nextToken().trim();
				    String fone1 = st.nextToken().trim();
				    String fone2 = st.nextToken().trim();
				    String fone3 = st.nextToken().trim();
				    String cpfCnpj = st.nextToken().trim();
				    String endereco = st.nextToken().trim();
				    String complemento = st.nextToken().trim();
				    String referencia = st.nextToken().trim();
				    String bairro = st.nextToken().trim();
				    String cep = st.nextToken().trim();
				    String cidade = st.nextToken().trim();
				    String estado = st.nextToken().trim();
				    String desconto = st.nextToken().trim();
				    String resgata = st.nextToken().trim();
				    
				    BigDecimal valor = BigDecimal.ZERO;
				    
				    try {
						valor = new BigDecimal(desconto.replace(",", "."));
					} catch (Exception e) {
					}

				    Cliente cliente = new Cliente();
				    cliente.setNome(nome);
				    cliente.setResponsavel(responsavel);
				    cliente.setFone(fone1);
				    cliente.setFone2(fone2);
				    cliente.setFone3(fone3);
				    cliente.setCpf(cpfCnpj);
				    cliente.setEndereco(endereco);
				    cliente.setComplemento(complemento);
				    cliente.setReferencia(referencia);
				    cliente.setBairro(bairro);
				    cliente.setCep(cep);
				    cliente.setCidade(cidade);
				    cliente.setEstado(estado);
				    cliente.setDesconto(valor);
				    if (resgata != null && ("S".equalsIgnoreCase(resgata.toLowerCase()) || "Sim".equalsIgnoreCase(resgata.toLowerCase()))) {
				    	cliente.setResgataUltimoPedido(Cliente.SIM);
				    } else {
				    	cliente.setResgataUltimoPedido(Cliente.NAO);
				    }

				    listaCliente.add(cliente);
				    
				} catch (java.util.NoSuchElementException e) {
					throw new DescricaoException("Erro ao percorrer a linha " + cont);
				}
			}
		    cont++;
		}
		
		List<Cliente> retorno = new ArrayList<Cliente>();
		for (Cliente coop : listaCliente) {
			retorno.add(this.getDelegate().insert(coop));
		}
		
		return retorno;
	}

}
